/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jingbit.ai.bt;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.tbruyelle.rxpermissions.RxPermissions;

import rx.functions.Action1;

/**
 * This is the main Activity that displays the current chat session.
 */
public class BluetoothActivity extends Activity implements Handler.Callback {
    // Debugging
    private static final String TAG = "jingbit";

    // Key names received from the BluetoothService Handler
    public static final String DEVICE_NAME = "device_name";
    public static final String TOAST = "toast";

    // Intent request codes
    private static final int REQUEST_CONNECT_DEVICE = 1;
    private static final int REQUEST_ENABLE_BT = 2;

    // Layout Views
    private TextView mTitle;

    // Name of the connected device
    private String mConnectedDeviceName = "";
    // Array adapter for the conversation thread
    private ArrayAdapter<String> mConversationArrayAdapter;
    // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    // Member object for the chat services
    private BluetoothService btService = null;
    private TextView tv_pwm1;
    private SeekBar sb_angle1;
    private TextView tv_pwm2;
    private SeekBar sb_angle2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_demo);
        // Android 版本大于等于 12 时，申请新的蓝牙权限
        new RxPermissions(this)
                .request(Manifest.permission.BLUETOOTH,
                        Manifest.permission.BLUETOOTH_ADMIN,
                        Manifest.permission.BLUETOOTH_PRIVILEGED,
                        Manifest.permission.ACCESS_COARSE_LOCATION,
                        Manifest.permission.ACCESS_FINE_LOCATION)//多个权限用","隔开
                .subscribe(new Action1<Boolean>() {
                    @Override
                    public void call(Boolean aBoolean) {
                        if (aBoolean) {
                            //当所有权限都允许之后，返回true
                            Log.i("permissions", "btn_more_sametime：" + aBoolean);
                        } else {
                            //只要有一个权限禁止，返回false，下一次申请只申请没通过申请的权限
                            Log.i("permissions", "btn_more_sametime：" + aBoolean);
                        }
                    }
                });

        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);

        mTitle = findViewById(R.id.title_right_text);

        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // If the adapter is null, then Bluetooth is not supported
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        tv_pwm1 = findViewById(R.id.tv_pwm1);
        sb_angle1 = findViewById(R.id.sb_angle1);
        sb_angle1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                tv_pwm1.setText("舵机1：" + progress + "°");
                btService.write(BluetoothService.MSG_PWM3_SIGN, BluetoothUtil.angleToPwm(progress, BluetoothService.MSG_PWM3_ANGLE_HALF));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        tv_pwm2 = findViewById(R.id.tv_pwm2);
        sb_angle2 = findViewById(R.id.sb_angle2);
        sb_angle2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                tv_pwm2.setText("舵机2：" + progress + "°");
                btService.write(BluetoothService.MSG_PWM1_SIGN, BluetoothUtil.angleToPwm(progress, BluetoothService.MSG_PWM1_ANGLE_HALF));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }


    public void clickHandler(View view) {
        int id = view.getId();
        if (id == R.id.btn1) {
            tv_pwm1.setText("舵机1：BluetoothService.MSG_PWM3_ANGLE_HALF°");
            sb_angle1.setProgress(BluetoothService.MSG_PWM3_ANGLE_HALF);
            tv_pwm2.setText("舵机2：BluetoothService.MSG_PWM1_ANGLE_HALF°");
            sb_angle2.setProgress(BluetoothService.MSG_PWM1_ANGLE_HALF);
            btService.write(BluetoothService.MSG_RESET_SIGN, 0);
        } else if (id == R.id.btn2) {
            Intent serverIntent = new Intent(this, BluetoothDeviceActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
        } else if (id == R.id.btn4) {//                value = new byte[1];
//                value[0] = (byte) 'K';
//                btService.write(value);
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
            // Otherwise, setup the chat session
        } else {
            if (btService == null)
                setupChat();
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        // Performing this check in onResume() covers the case in which BT was
        // not enabled during onStart(), so we were paused to enable it...
        // onResume() will be called when ACTION_REQUEST_ENABLE activity
        // returns.
        if (btService != null) {
            // Only if the state is STATE_NONE, do we know that we haven't
            // started already
            if (btService.getConnectState() == BluetoothService.STATE_NONE) {
                // Start the Bluetooth chat services
                btService.start();
            }
        }
    }

    private void setupChat() {
        Log.d(TAG, "setupChat");

        // Initialize the array adapter for the conversation thread
        mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);

        // Initialize the BluetoothService to perform bluetooth connections
        btService = new BluetoothService(this,this);
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    private void ensureDiscoverable() {
        if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
            startActivity(discoverableIntent);
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case BluetoothService.MSG_STATE_CHANGE:
                switch (msg.arg1) {
                    case BluetoothService.STATE_CONNECTED:
                        mTitle.setText(R.string.title_connected_to);
                        mTitle.append(mConnectedDeviceName);
                        mConversationArrayAdapter.clear();
                        btService.write(BluetoothService.MSG_RESET_SIGN, 0);
                        break;
                    case BluetoothService.STATE_CONNECTING:
                        mTitle.setText(R.string.title_connecting);
                        break;
                    case BluetoothService.STATE_LISTEN:
                    case BluetoothService.STATE_NONE:
                        mTitle.setText(R.string.title_not_connected);
                        break;
                }
                break;
            case BluetoothService.MSG_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                String writeMessage = new String(writeBuf);
                mConversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case BluetoothService.MSG_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
                mConversationArrayAdapter.add(mConnectedDeviceName + ":  " + readMessage);
                Log.d(TAG, "MSG_READ：" + readMessage);
                if (readMessage.startsWith("jd")) {
                    try{
                        String[] strs = readMessage.split(":");
                        int index = BluetoothUtil.getAngleIndex(strs[0]);
                        int pwm = Integer.parseInt(strs[1]);
                        int angle = BluetoothUtil.pwmToAngle(pwm, BluetoothService.ANGLE_VS[index]);
                        Log.d(TAG, "MSG_READ1：" + pwm+ "---" + angle);
                        switch (index){
                            case 0:
                                BluetoothService.MSG_PWM1_ANGLE=angle;
                                break;
                            case 1:
                                BluetoothService.MSG_PWM2_ANGLE=angle;
                                break;
                            case 2:
                                BluetoothService.MSG_PWM3_ANGLE=angle;
                                break;
                            case 3:
                                BluetoothService.MSG_PWM4_ANGLE=angle;
                                break;
                            case 4:
                                BluetoothService.MSG_PWM5_ANGLE=angle;
                                break;
                            case 5:
                                BluetoothService.MSG_PWM6_ANGLE=angle;
                                break;
                        }
                    }
                    catch (Exception e){}
                }
                break;
            case BluetoothService.MSG_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = (String) msg.obj;
                Toast.makeText(getApplicationContext(), "Connected to " + mConnectedDeviceName, Toast.LENGTH_SHORT)
                        .show();
                break;
            case BluetoothService.MSG_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show();
                break;
        }
        return false;
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_CONNECT_DEVICE:
                // When BluetoothDeviceActivity returns with a device to connect
                if (resultCode == Activity.RESULT_OK) {
                    // Get the device MAC address
                    String address = data.getExtras().getString(BluetoothDeviceActivity.EXTRA_DEVICE_ADDRESS);

                    Log.d(TAG, "onActivityResult：" + address);// Get the BLuetoothDevice object
                    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
                    // Attempt to connect to the device
                    btService.connect(device);
                }
                break;
            case REQUEST_ENABLE_BT:
                // When the request to enable Bluetooth returns
                if (resultCode == Activity.RESULT_OK) {
                    // Bluetooth is now enabled, so set up a chat session
                    setupChat();
                } else {
                    // User did not enable Bluetooth or an error occured
                    Log.d(TAG, "BT not enabled");
                    Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                    finish();
                }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.option_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int itemId = item.getItemId();
        if (itemId == R.id.scan) {// Launch the BluetoothDeviceActivity to see devices and do scan
            Intent serverIntent = new Intent(this, BluetoothDeviceActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
            return true;
        } else if (itemId == R.id.discoverable) {// Ensure this device is discoverable by others
            ensureDiscoverable();
            return true;
        }
        return false;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // Stop the Bluetooth chat services
        if (btService != null)
            btService.stop();
    }


}